/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.brainstretch.recommend;

import java.util.EnumMap;
import org.brainstretch.models.quizzes.Category;

/**
 *
 * @author mrodaitis
 */
public class ProfileVector {
    
    private Profile profile;

    private EnumMap<ProfileDimension, Double> propertyMap;
    private EnumMap<Category, Double> categoryMap;
    
    public ProfileVector(Profile profile) {
        this.profile = profile;
        propertyMap = new EnumMap<ProfileDimension, Double>(ProfileDimension.class);
        categoryMap = new EnumMap<Category, Double>(Category.class);
        initPropertyMap();
        initCategoryMap();
    }
    
    private void initPropertyMap(){
        propertyMap.put(ProfileDimension.Duration, profile.getDuration());
        propertyMap.put(ProfileDimension.AnswerLength, profile.getAverageAnswerLength());
        propertyMap.put(ProfileDimension.AttmeptsPerQuestion, profile.getAverageAttemptsPerQuestion());
        propertyMap.put(ProfileDimension.AvgScore, profile.getAverageScore());
        propertyMap.put(ProfileDimension.QuestionLength, profile.getAverageQuestionLength());
        propertyMap.put(ProfileDimension.QuestionsPerSet, profile.getQuestionsPerSet());
        propertyMap.put(ProfileDimension.TimePerQuestion, profile.getTimePerQuestion());
    }
    
    private void initCategoryMap(){
        for(Category cat: Category.values()){
            categoryMap.put(cat, profile.getCategoryWeight(cat));
        }
    }
    
    public void normalize(EnumMap<ProfileDimension, Double> normMap){
        normalizeExternal(normMap);
        normalizeInternal();
    }
    
    public void normalizeExternal(EnumMap<ProfileDimension, Double> normMap){
        for(ProfileDimension dim: normMap.keySet()){
            double max = normMap.get(dim);
            if(max != 0){
                propertyMap.put(dim, propertyMap.get(dim)/normMap.get(dim));
            }
        }
    }
    
    public void normalizeInternal(){
        double length = calcLength();
        scale(1.0/length);
    }
    
    public void scale (double factor){
        for(ProfileDimension dim: propertyMap.keySet()){
            propertyMap.put(dim, propertyMap.get(dim) * factor);
        }
        for(Category cat: categoryMap.keySet()){
            categoryMap.put(cat, categoryMap.get(cat) * factor);
        }
    }
    

    private double calcLength() {
        double len = 0;
        for(ProfileDimension dim: propertyMap.keySet()){
            len += propertyMap.get(dim) * propertyMap.get(dim);
        }
        for(Category cat: categoryMap.keySet()){
            len += categoryMap.get(cat) * categoryMap.get(cat);
        }
        return Math.sqrt(len);
    }
    
    public double getPropertyWeight(ProfileDimension dim){
        double value = 0;
        if(propertyMap.containsKey(dim)){
            value = propertyMap.get(dim);
        }
        return value;
    }
    
    public void setPropertyWeight(ProfileDimension dim, double weight){
        propertyMap.put(dim, weight);
    }
    
    public void setCategoryWeight(Category cat, double weight){
        categoryMap.put(cat, weight);
    }
    
    public double getCategoryWeight(Category cat){
        double value = 0;
        if(categoryMap.containsKey(cat)){
            value = categoryMap.get(cat);
        }
        return value;
    }
    
    public double cosineSimilarity(ProfileVector other){
        double prod = 0;
        for(ProfileDimension dim: propertyMap.keySet()){
            prod += propertyMap.get(dim) * other.getPropertyWeight(dim);
        }
        for(Category cat: categoryMap.keySet()){
            prod += categoryMap.get(cat) * other.getCategoryWeight(cat);
        }
        return prod;
    }
    
    
    
    
}
